import { initData, store } from '../store.js';

import WK from '../workerManager/index.js';
// import '../utils/logger.js';
import { Worker } from 'node:worker_threads';
import _ from 'lodash';
import { sendMessage } from '../utils/websocket.js';
import { v4 as uuid } from 'uuid';

/**
 * manager
 */
const manager = {
    /**
     * 每一个worker最大线程
     */
    maxThreads: 100,
    // initData消息超时
    // timeout: 10 * 1000,//3秒
    msgTimeout: 10 * 1000,
    // worker最大占用时间
    timeout: 10 * 60000, //10分秒毫秒
    queue: {
        // 'appid_version': {
        //     'uniqueId': {
        //         count: 0,
        //         createTime: 1702018266418,
        //         path: 'E:\\gitlabWrok-App\\background\\tmp\\018b41bc-1ad0-a010-dcb5-fc2fc1a355e6-0.0.1-1.js',
        //         worker: [Worker]
        //     }
        // }
    },
    mountWorker(wk) {
        wk.worker.on('error', (e) => {
            console.error('worker error:>>>', e);
            // console.error('worker error:>>>', JSON.stringify(e))
        });

        wk.worker.on('exit', (e) => {
            console.log('worker close', e);
        });
        wk.worker.on('message', (message) => {
            debugger;
            console.log('worker message >>>sendMessagesendMessagesendMessagesendMessage', message);
            debugger;
            // 节点给服务器：调用方法
            if (message?.type === 'method') {
                // 保存回调
                store[message.id] = {
                    wk: wk,
                    timeStamp: Date.now(),
                    payload: message,
                };
                // 尝试将内容整理成一个数组，在这里拼接
                //小应用主动发送消息
                sendMessage(JSON.stringify(message));
                // TODO:拦截所有小应用的信息，修改method发出去
            }

            // 小应用发送的init结果上报云端和主线程保存
            if (message?.type === 'init') {
                const data = message.data;
                const appInfo = message.appInfo;
                const appName = appInfo.appId + '_' + appInfo.appReleaseType;

                if (!initData[appName]) {
                    initData[appName] = {};
                }

                initData[appName][appInfo.userId] = {
                    data,
                    timeStamp: Date.now(),
                };

                sendMessage(
                    JSON.stringify({
                        ...message,
                        type: 'initData',
                    }),
                );
            }
            if (message === 'workerEnd') {
                debugger;
                wk.count--;
                // todo开发看数据 后期删除
                let data = {};
                for (let key in WK.queue) {
                    data[key] = {};
                    for (let x in WK.queue[key]) {
                        data[key][x] = {
                            count: WK.queue[key][x].count,
                            createTime: WK.queue[key][x].createTime,
                        };
                    }
                    console.info('⬇⬇⬇⬇⬇⬇⬇⬇队列数据⬇⬇⬇⬇⬇⬇⬇⬇');
                    console.log(data);
                    console.info('⬆⬆⬆⬆⬆⬆⬆⬆队列数据⬆⬆⬆⬆⬆⬆⬆⬆');
                }
            }

            if (message?.type === 'nodeResponse') {
                // console.log('!!!!!!!!!!!!!!!!!!!!!!!!!', message)
                sendMessage(JSON.stringify(message));
            }

            // 从nodejs转发到这里。
            if (message?.type == 'sendMessage') {
                // TODO:拦截所有小应用的信息，修改method---sendMessage发出去
                // 保存回调
                store[message.id] = {
                    wk: wk,
                    timeStamp: Date.now(),
                    payload: message,
                };
                // 尝试将内容整理成一个数组，在这里拼接
                //小应用主动发送消息
                sendMessage(JSON.stringify(message));
            }
        });

        wk.worker.on('messageerror', (e) => {
            console.error('worker messageerror:>>>', JSON.stringify(e.message));
        });

        wk.worker.on('online', () => {
            console.log('worker online');
        });

        return wk;
    },
    /**
     * 获取worker
     * @param {*} appInfo
     * @returns worker|null
     * 该类型应用不存在返回null 存在返回woker对象
     * mountWorkerEvent 创建完成以后执行的函数（挂载Worker的event）
     */
    getWorker(payload) {
        const appInfo = payload.appInfo;
        const key = appInfo.appId + '_' + appInfo.appReleaseType;

        if (manager.queue[key]) {
            for (const x in manager.queue[key]) {
                const value = manager.queue[key][x];

                if (value.count >= manager.maxThreads) {
                    console.log('当前大于了100===》', key, x);
                    continue;
                }

                manager.queue[key][x].count++;
                manager.queue[key][x].createTime = Date.now();
                console.log(x, '--', manager.queue[key][x].count);

                return manager.queue[key][x];
            }
            const firstKey = Object.keys(manager.queue[key])[0];
            return manager.createWorker(payload, manager.queue[key][firstKey].path);
        }
        return null;
    },
    /**
     * 创建worker
     * @param {*} appInfo
     * @param {*} workerFilePath
     * @returns  返回worker
     */
    createWorker(payload, workerFilePath) {
        const appInfo = payload.appInfo;
        let key = appInfo.appId + '_' + appInfo.appReleaseType;

        const id = _.uniqueId();

        let obj = {
            count: 1, //从1开始 调用者不需要再++
            createTime: Date.now(),
            path: workerFilePath,
            worker: new Worker(workerFilePath),
        };
        debugger;
        if (!manager.queue[key]) {
            manager.queue[key] = {
                [id]: obj,
            };
        } else {
            manager.queue[key][id] = obj;
        }

        manager.executeAppRecycling();
        console.log('createWorker', key, id, manager.queue[key][id].count);

        // 挂载Worker event
        debugger;
        console.log(manager.queue[key][id], 'mountWorker');
        manager.mountWorker(manager.queue[key][id]);

        // 初始化小应用
        manager.queue[key][id].count++;
        manager.queue[key][id].worker?.postMessage({
            ...payload,
            cmd: {
                fn: 'create',
            },
        });

        //是否调用init
        // console.log('是否调用init', !payload.initData && !(initData[key] && initData[key][appInfo.userId]))
        if (!payload.initData && !(initData[key] && initData[key][appInfo.userId])) {
            console.log('调用init>>', key, id);
            manager.queue[key][id].count++;
            manager.queue[key][id].createTime = Date.now();
            // console.log('count', manager.queue[key][id])
            manager.queue[key][id].worker?.postMessage({
                ...payload,
                cmd: {
                    fn: 'init',
                },
            });
        }
        return manager.queue[key][id];
    },
    /**
     * 关闭应用
     * @param {*} appInfo
     */
    stopWorker(appInfo) {
        let key = appInfo.appId + '_' + appInfo.appReleaseType;

        for (let x in manager.queue[key]) {
            manager.queue[key][x].worker.terminate();
        }

        // 清空该应用所有的数据
        delete initData[key];
        // store 的数据没有包裹应用key，10秒自动删除

        // 删除worker
        delete manager.queue[key];
    },
    /**
     * 执行APP回收
     */
    interval: null,
    executeAppRecycling() {
        if (manager.interval) {
            return;
        }
        manager.interval = setInterval(() => {
            // 清空 所有队列的worker
            if (Object.keys(manager.queue).length == 0) {
                console.log('关闭定时器', manager.queue);

                clearInterval(manager.interval);

                manager.interval = null;

                // 清除所有数据
                for (let key in initData) {
                    delete initData[key];
                }
                for (let key in store) {
                    delete store[key];
                }
                console.log('清除所有数据', initData);
                return;
            }

            // 清除数据
            for (let key in initData) {
                if (Object.keys(initData[key]).length == 0) {
                    delete initData[key];
                }

                for (let x in initData[key]) {
                    if (Date.now() - initData[key][x].timeStamp >= manager.timeout) {
                        // console.log('清除数据', key, x)
                        delete initData[key][x];
                    }
                }
            }

            // 清除msgCallback
            for (let key in store) {
                // console.log(Date.now() - store[key].timeStamp, (Date.now() - store[key].timeStamp) >= manager.msgTimeout)
                if (Date.now() - store[key].timeStamp >= manager.msgTimeout) {
                    let { payload, wk } = store[key];
                    if (wk) {
                        wk.count++;
                        wk.createTime = Date.now();
                        wk.worker?.postMessage({
                            ...payload,
                            type: 'response',
                            response: {
                                code: 500,
                                message: '超时',
                            },
                        });
                    }
                    delete store[key];
                }
            }

            // 清除应用
            for (let key in manager.queue) {
                if (Object.keys(manager.queue[key]).length == 0) {
                    delete manager.queue[key];

                    // 上报stop
                    const message = {
                        id: uuid(),
                        type: 'nodeResponse',
                        timestamp: +new Date(),
                        appInfo: {
                            appId: key.split('_')[0],
                            appReleaseType: key.split('_')[1],
                        },
                        result: {
                            code: 200,
                            type: 'stop',
                        },
                    };
                    sendMessage(JSON.stringify(message));

                    continue;
                }
                // 检查每一个worker的时间是否超过了10分钟
                for (let x in manager.queue[key]) {
                    if (Date.now() - manager.queue[key][x].createTime >= manager.timeout) {
                        console.log('清除并删除woker', key, '___', x);
                        manager.queue[key][x].worker.terminate();
                        delete manager.queue[key][x];
                    }
                }
            }

            // 日志 遍历定时器 上线前删除
            // let data = {}
            // for (let key in manager.queue) {
            //     data[key] = {}
            //     for (let x in manager.queue[key]) {
            //         data[key][x] = {
            //             count: manager.queue[key][x].count,
            //             createTime: manager.queue[key][x].createTime,
            //         }
            //     }
            //     console.log('定时器数据', data)
            // }
            // console.log('定时器数据', manager.queue)
        }, 1000);
    },
};

export default manager;
